const speed = 1000;
const gravity = -640;
const gravityScale = 1;

cc.Class({
    extends: cc.Component,
    properties: {
        lineTemp: cc.Node,
        lineArrow: cc.Node,
        targetTile: cc.Node,
        btnOK: cc.Node,
        btnNO: cc.Node,
        cameraNode: cc.Node,
        parentNode: cc.Node
    },

    // LIFE-CYCLE CALLBACKS:

    onLoad() {
        this._lineArray = [];
        this._curLineArray = [];
        this._bulletList = [];
        for (let i = 0; i < 50; i++) {
            this.getFreeNode(true);
        }
        cc.game.on('CHECK_LEAGUE_ATTACK_IS_OK', this.onCheckPos, this);
    },

    start() {
        this.startCheck(cc.v2(0, 0));
    },

    //开始检测
    startCheck(startPos) {
        this._offsetP = cc.v2(200, 0);
        this._isCheck = true;
        this._startPos = startPos;
        this.onCheckPos(cc.v2(0, 0));
    },

    onCheckPos(deltaP) {
        if (!this._isCheck || this._isFire) return;
        this._offsetP.subSelf(deltaP);
        let endP = this._startPos.add(this._offsetP);
        this.cameraNode.x = endP.x;
        this.cameraNode.y = endP.y - 667;
        this.init(endP);
    },

    resetLineArray() {
        for (let i = 0; i < this._lineArray.length; i++) {
            let node = this._lineArray[i];
            node.opacity = 0;
        }
    },

    getFreeNode(isNew) {
        if (isNew) {
            let node = cc.instantiate(this.lineTemp);
            node.parent = this.node;
            node.opacity = 255;
            this._lineArray.push(node);
            return node;
        } else {
            for (let i = 0; i < this._lineArray.length; i++) {
                let node = this._lineArray[i];
                if (node.opacity === 0) {
                    node.opacity = 255;
                    return node;
                }
            }
            return this.getFreeNode(true);
        }
    },

    createBullet(data) {
        let node = new cc.Node();
        let sprite = node.addComponent(cc.Sprite);
        cc.loader.loadRes(`world/img_find_icon_stone`, cc.SpriteFrame, (err, sp) => {
            sprite.spriteFrame = sp;
        })
        cc.tween(node).by(0.5, {angle: -360}).repeatForever().start();
        node.parent = this.parentNode;
        node.position = data.startP;
        data.node = node;
        node.group = 'map';
        this._bulletList.push(data);
    },

    startFire(startP, endP, isMy) {
        let v = this.caculateV(startP, endP);
        let result = this.caculateTime(v, startP, endP);
        let data = {
            totalTime: result.totalTime,
            startP: startP,
            endP: endP,
            v: v,
            time: 0,
            isFinish: false,
            isMy: isMy
        }
        if (result.totalTime > 0) {
            this.createBullet(data);
        }
    },


    drawLine(startP, endP, listP) {
        this.resetLineArray();
        this._curLineArray.length = 0;
        let isOk = true;
        let color = isOk ? new cc.Color(0, 255, 0) : new cc.Color(255, 0, 0);
        this.btnOK.getComponent(cc.Button).interactable = isOk;
        this.targetTile.position = endP;
        this.targetTile.color = color;
        for (let i = 0; i < listP.length; i++) {
            let node = this.getFreeNode();
            if (i === listP.length - 1) {
                node = this.lineArrow;
            }
            let p = listP[i];
            let index = this._curLineArray.length - 1;
            if (index >= 0) {
                let lastNode = this._curLineArray[index];
                lastNode.offsetP = p.sub(lastNode.position);
                lastNode.lastP = lastNode.position;
                lastNode.dt = 0;
            }
            if (i < listP.length - 1) {
                this._curLineArray.push(node);
            }
            let lastIndex = i - 1;
            let lastP = startP;
            if (lastIndex >= 0) {
                lastP = listP[lastIndex];
            }
            let rotation = mike.math.getAngle(lastP, p);
            node.angle = -rotation;
            node.opacity = 255;
            node.position = p;
            node.color = color;
        }
    },

    caculateTime(v, startP, endP) {
        const dt = 5 / 60;
        let isDown = false;
        let preP = cc.v2(0, 0);
        let isLast = false;
        let totalTime = -1;
        let listP = [];
        for (let count = 0; count < 100; count++) {
            let time = dt * count;
            let offsetP = this.caculatePos(v, time);
            let targetP = startP.add(offsetP);
            if (preP.y > offsetP.y) {
                isDown = true;
            }
            if (isDown && targetP.y < endP.y) {
                isLast = true;
                targetP = endP;
            }
            preP = offsetP;
            listP.push(targetP);
            if (isLast) {
                totalTime = time;
                break;
            }
        }
        return {totalTime: totalTime, listP: listP};
    },

    caculateV(startP, endP) {
        let s = endP.x - startP.x;
        let h = endP.y - startP.y;
        let a = gravity * gravityScale * s / (2 * speed * speed);
        let b = 1;
        let c = a - h / s;
        let delta = b * b - 4 * a * c;
        let v = cc.Vec2.ZERO;
        if (delta >= 0) {
            // 一元二次方程求根公式
            let t2 = (-b - Math.sqrt(delta)) / (2 * a); // 高抛 tan 值
            // 二、三象限角度要加 180
            let alpha2 = Math.atan(t2) + (s < 0 ? Math.PI : 0);
            let v_x_2 = Math.cos(alpha2) * speed;
            let v_y_2 = Math.sin(alpha2) * speed;
            v = cc.v2(v_x_2, v_y_2);
        }
        return v;
    },

    init(targetPos) {
        this._linearVelocity = cc.v2(0, 0);
        this._endPos = targetPos;
        let v = this.caculateV(this._startPos, this._endPos);
        this._linearVelocity = v;
        let startTileP = this._startPos;
        this._startTileP = startTileP;
        let endTileP = this._endPos;
        this._endTileP = endTileP;
        let result = this.caculateTime(v, this._startPos, this._endPos);
        this.drawLine(this._startPos, this._endPos, result.listP);
    },

    updateBullet(dt) {
        if (this._bulletList.length > 0) {
            let removeList = [];
            for (let i = 0; i < this._bulletList.length; i++) {
                let data = this._bulletList[i];
                if (!data.isFinish) {
                    data.time += dt;
                    let node = data.node;
                    let offset = this.caculatePos(data.v, data.time);
                    node.position = data.startP.add(offset);
                    if (data.time >= data.totalTime) {
                        node.destroy();
                        removeList.push(i);
                        data.isFinish = true;
                        if (data.isMy) {
                            this.node.opacity = 255;
                            this.btnOK.active = true;
                            this.btnNO.active = true;
                            this._isFire = false;
                            this._time = 0;
                        }
                    }
                }
            }
            if (removeList.length > 0) {
                let sortDis = (a, b) => {
                    return b - a;
                }
                removeList.sort(sortDis);
                removeList.forEach((index) => {
                    this._bulletList.splice(index, 1);
                })
            }
        }
    },

    updateLine(dt) {
        if (this._curLineArray) {
            for (let i = 0; i < this._curLineArray.length; i++) {
                let node = this._curLineArray[i];
                if (!node.offsetP || !node.lastP) continue;
                if (!node.dt) node.dt = 0;
                node.dt += dt;
                if (node.dt > 1) node.dt = 0;
                let lastP = node.position;
                node.position = node.offsetP.mul(node.dt).add(node.lastP);
                let rotation = mike.math.getAngle(lastP, node.position);
                node.angle = -rotation;
                if (i === this._curLineArray.length - 1) {
                    node.opacity = (1 - node.dt) * 255;
                }
            }
        }
    },

    update(dt) {
        this.updateLine(dt);
        this.updateBullet(dt);
    },

    convertWorldToScreenPos(p) {
        p = this.cameraNode.getComponent(cc.Camera).MyScreenToWorld(p);
        // //let pp = cc.v3(p.x, p.y, 0);
        // for (let i = 0; i < cc.Camera.cameras.length; i++) {
        //     let camera = cc.Camera.cameras[i];
        //     if (camera.name === 'MapCamera<MyCamera>') {
        //         var p2 = camera.getWorldToScreenPoint(p);
        //         var p3 = this.node.convertToNodeSpaceAR(p2);
        //         p = p3;
        //         break;
        //     }
        // }
        return p;
    },

    setRectArray(array) {
        this._rectArray = array;
    },

    hide() {
        this.node.opacity = 0;
        this.btnOK.active = false;
        this.btnNO.active = false;
        this._isCheck = false;
    },

    show() {
        this.node.opacity = 255;
        this.btnOK.active = true;
        this.btnNO.active = true;
        this._isFire = false;
        this._time = 0;
    },

    onBtnOK() {
        this.fire();
    },

    onBtnNo() {

    },

    caculatePos(v, time) {
        const dx = v.x * time;
        const dy = v.y * time + 0.5 * gravity * gravityScale * time * time;
        let offsetP = cc.v2(dx, dy);
        return offsetP;
    },

    fire() {
        if (this._isCheck) {
            this._isFire = true;
            this.btnOK.active = false;
            this.btnNO.active = false;
            this.startFire(this._startTileP, this._endTileP, true);
        }
    }
});
